﻿using System.Diagnostics;
using System.Text;

using Microsoft.EntityFrameworkCore;

using SManaApi.Extensions;

using SManaModel;
using SManaModel.dtos;
using SManaModel.entities;
using SManaModel.entities.constant;
using SManaModel.models;

namespace SManaApi.Services;

public class ApproveService : BaseService<ApproveEntity>
{
    public ApproveService(MyDbContext dbContext) : base(dbContext)
    {
    }

    /// <summary>
    /// 教师获取学生的申请
    /// </summary>
    /// <param name="teaId">老师id</param>
    /// <returns></returns>
    public List<ApproveEntity> GetApprovesForTeacher(int teaId)
    {
        var approveList = _dbContext.Approve!.Include(t => t.ApplyStudent).OrderByDescending(t => t.CDate).Where(t =>
                t.ApplyStudent.Teacher_Id == teaId || t.ApplyStudent.Teacher2_Id == teaId)
            .ToList();
        return approveList;
    }

    /// <summary>
    /// 取消申请
    /// </summary>
    /// <param name="approveId">申请id</param>
    /// <returns></returns>
    public int CancelApproveForStudent(int approveId)
    {
        var n = _dbContext.BeginTransaction<int>((db, trans) =>
        {
            var approveEntity = GetEntity(t => t.Id == approveId)?.FirstOrDefault();
            if (approveEntity == null)
                return 0;

            #region 修改状态

            approveEntity.Status = ApproveStatusEnum.Cancel.ToString();
            var n = UpdateEntity(approveEntity, db);

            #endregion

            #region 添加日志

            ApproveLogEntity log = new()
            {
                Content = $"学生[{approveEntity.ApplyStudentId}]取消申请[{approveEntity.Id}]",
                ApproveId = approveEntity.Id,
                Event = ApproveLogEventConst.CancelApply,
                StudentId = approveEntity.ApplyStudentId,
            };

            db.ApproveLog.Add(log);
            n += db.SaveChanges();

            #endregion

            trans.Commit();
            return n;
        });
        return n;
    }

    /// <summary>
    /// 学生获取申请信息
    /// </summary>
    /// <param name="pageDto">分页组件</param>
    /// <param name="stuId">学生id</param>
    /// <returns></returns>
    public PageApiResult GetApprovesForStudent(SearchPageDto pageDto, int stuId)
    {
        var pendingList = _dbContext.Approve
            !.Include(t => t.ApplyStudent)
            .ThenInclude(t => t.Teacher)
            .Include(t => t.ApplyStudent)
            .ThenInclude(t => t.Teacher2)
            .Where(t => t.ApplyStudentId == stuId)
            .OrderByDescending(t=>t.CDate)
            .Select(approve => new ApproveDto
            {
                id = approve.Id,
                t1id = approve.ApplyStudent.Teacher_Id,
                t2id = approve.ApplyStudent.Teacher2_Id,
                t1name = approve.ApplyStudent.Teacher.Name,
                t2name = approve.ApplyStudent.Teacher2.Name,
                tstatus = approve.TeacherApproveStatus,
                t2status = approve.TeacherApprove2Status,
                status = approve.Status,
                doc_path = approve.DocPath,
                cdate = approve.CDate,
                position = approve.ApplyPosition,
                title = approve.Title,
                reason = approve.Reason,
                sid = approve.ApplyStudentId,
            });
        var outList = pageDto.Pager(pendingList)!.ToList();
        var count = _dbContext.Approve
            !.Include(t => t.ApplyStudent)
            .Where(t => t.ApplyStudentId == stuId)
            !.Count();

        var pageApiResult = new PageApiResult
        {
            list = outList,
            totalNum = count
        };
        return pageApiResult;
    }

    /// <summary>
    /// 老师获取学生的申请信息
    /// </summary>
    /// <param name="generalPageDto"></param>
    /// <param name="teaId"></param>
    /// <returns></returns>
    public PageApiResult GetApprovesForTeacher(SearchPageDto generalPageDto, int teaId)
    {
        var servicePageComponent = ServicePageComponent<ApproveEntity, DateTime>.Create(
            PageComponent.Create(generalPageDto),
            entity => entity.CDate,
            entity => true,
            false);

        var pendingList = _dbContext.Approve!
            .Include(t => t.ApplyStudent)
            .ThenInclude(t => t.Teacher)
            .Include(t => t.ApplyStudent)
            .ThenInclude(t => t.Teacher2)
            .OrderByDescending(servicePageComponent.OrderByExpression!)
            .Where(t => t.ApplyStudent.Teacher_Id == teaId || t.ApplyStudent.Teacher2_Id == teaId);

        var outList = pendingList.Pager(servicePageComponent)
            !.Select(approve =>
                new ApproveDto
                {
                    id = approve.Id,
                    t1id = approve.ApplyStudent.Teacher_Id,
                    t2id = approve.ApplyStudent.Teacher2_Id,
                    t1name = approve.ApplyStudent.Teacher.Name,
                    t2name = approve.ApplyStudent.Teacher2.Name,
                    tstatus = approve.TeacherApproveStatus,
                    t2status = approve.TeacherApprove2Status,
                    status = approve.Status,
                    doc_path = approve.DocPath,
                    cdate = approve.CDate,
                    position = approve.ApplyPosition,
                    title = approve.Title,
                    reason = approve.Reason,
                    sid = approve.ApplyStudentId,
                    sname = approve.ApplyStudent.Name,
                }
            )
            !.ToList();
        var count = pendingList.Count();
        var pageApiResult = new PageApiResult
        {
            list = outList,
            totalNum = count
        };
        return pageApiResult;
    }

    /// <summary>
    /// 查看审批表里是否已经选择此老师当培养人
    /// </summary>
    /// <param name="stuId">学生id</param>
    /// <param name="teaId">教师id</param>
    /// <returns></returns>
    public int JudgeApplyTeacher(int stuId, int teaId)
    {
        var count = _dbContext.Student
            !.Where(t => t.Id == stuId && (t.Teacher_Id == teaId || t.Teacher2_Id == teaId))?.Count();
        count ??= 0;
        return count.Value;
    }

    /// <summary>
    /// 操作申请
    /// </summary>
    /// <param name="approveId">审批id</param>
    /// <param name="teaId">教师id</param>
    /// <param name="ok">true 批准, false 驳回</param>
    /// <param name="order">教师序号</param>
    /// <param name="applyContent">批准内容</param>
    /// <param name="refuteContent">驳回内容</param>
    /// <returns></returns>
    public int ApplyApprove(int approveId, int teaId, bool ok, int order, string applyContent = "符合条件",
        string refuteContent = "不符合条件")
    {
        var num = _dbContext.BeginTransaction<int>((db, trans) =>
        {
            var approveEntity = db.Approve!.Where(t => t.Id == approveId)?.FirstOrDefault();

            if (approveEntity == null || approveEntity.Status == ApproveStatusEnum.Cancel.ToString())
                return 0;

            bool isWriteProcess = false;

            #region 添加审批日志

            ApproveLogEntity approveLogEntity = new()
            {
                Other = $"{teaId}:{approveEntity.ApplyStudentId}",
                Event = "职位申请",
                StudentId = approveEntity.ApplyStudentId,
                TeacherId = teaId,
                ApproveId = approveEntity.Id
            };
            StringBuilder sb = new();
            if (ok)
            {
                sb.Append($"教师id {teaId} 批准 申请id {approveEntity.Id}");
                sb.Append("批准理由:" + applyContent);
            } // 批准
            else
            {
                sb.Append($"教师id {teaId} 驳回 申请id {approveEntity.Id}");
                sb.Append("驳回理由:" + refuteContent);
            } // 驳回

            approveLogEntity.Content = sb.ToString();
            db.ApproveLog.Add(approveLogEntity);
            var n = db.SaveChanges();

            #endregion

            #region 修改审批状态

            approveEntity.ApproveLogId = approveLogEntity.Id;

            if (order == 1)
            {
                approveEntity.TeacherApproveStatus =
                    ok ? TeacherApproveStatusEnum.Approved.ToString() : TeacherApproveStatusEnum.Confuted.ToString();
                approveEntity.ApproveLogId = approveLogEntity.Id;
            }
            else
            {
                approveEntity.TeacherApprove2Status =
                    ok ? TeacherApproveStatusEnum.Approved.ToString() : TeacherApproveStatusEnum.Confuted.ToString();
                approveEntity.ApproveLog2Id = approveLogEntity.Id;
            }

            // 判断两位培养人是否都已经批准
            if (approveEntity.TeacherApproveStatus.Equals(TeacherApproveStatusEnum.Approved.ToString())
                && approveEntity.TeacherApprove2Status.Equals(TeacherApproveStatusEnum.Approved.ToString()))
            {
                approveEntity.Status = ApproveStatusEnum.Approved.ToString();
                isWriteProcess = true;
            }
            else if (approveEntity.TeacherApproveStatus.Equals(TeacherApproveStatusEnum.Confuted.ToString())
                     || approveEntity.TeacherApprove2Status.Equals(TeacherApproveStatusEnum.Confuted.ToString()))
            {
                approveEntity.Status = ApproveStatusEnum.Confuted.ToString();
            }
            else if (approveEntity.Status != ApproveStatusEnum.Cancel.ToString())
            {
                approveEntity.Status = ApproveStatusEnum.Approving.ToString();
            }

            _dbContext.Update(approveEntity);
            n += _dbContext.SaveChanges();

            #endregion

            #region 判断是否写入发展进程

            if (!isWriteProcess)
            {
                trans.Commit();
                return n;
            }

            approveEntity = db.Approve!
                .Include(t => t.ApplyStudent)
                .Where(t => t.Id == approveId
                            && t.ApplyStudent.Teacher_Id != null
                            && t.ApplyStudent.Teacher2_Id != null)
                ?.FirstOrDefault();

            if (approveEntity != null)
            {
                ProcessEntity processEntity = new()
                {
                    ApproveId = approveEntity.Id,
                    StudentId = approveEntity.ApplyStudentId,
                    TeacherId = approveEntity.ApplyStudent.Teacher_Id!.Value,
                    Teacher2Id = approveEntity.ApplyStudent.Teacher2_Id!.Value,
                    Position = approveEntity.ApplyPosition!,
                };
                db.Add(processEntity);
                n += db.SaveChanges();
            }

            #endregion

            trans.Commit();
            return n;
        });
        return num;
    }
}